#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>   
#include <stdio.h>       
#include <stdlib.h>      
#include <string.h>      
#include <unistd.h>      

#define MAX_LEN  1024    /* maximum string size to send */
#define MIN_PORT 1024    /* minimum port allowed */
#define MAX_PORT 65535   /* maximum port allowed */


int MULTICAST_INTERVAL = 2;	/* in seconds */

int main(int argc, char *argv[]) 
{
	int sock;                   /* socket descriptor */
	struct sockaddr_in mc_addr; /* socket address structure */
	char* mc_addr_str;          /* multicast IP address ["225.0.0.37"] */
	unsigned short mc_port;     /* multicast port [12345]*/
	unsigned char mc_ttl=1;     /* time to live (hop count) */
	unsigned int node_type;

/* validate number of arguments */
	if (argc != 5) 
	{
		fprintf(stderr, "Usage: %s <Multicast IP> <Multicast Port> <Node Type> <MULTICAST INTERVAL> [Type: WEB SERVER = 1, LOG SERVER = 2]\n", argv[0]);
		exit(1);
	}

	mc_addr_str = argv[1];			/* arg 1: multicast IP address */
	mc_port     = atoi (argv[2]);	/* arg 2: multicast port number */
	node_type	= atoi (argv[3]);	
	MULTICAST_INTERVAL = atoi (argv[4]);


	/* validate the port range */
	if ((mc_port < MIN_PORT) || (mc_port > MAX_PORT)) 
	{
		fprintf(stderr, "Invalid port number argument %d.\n", mc_port);
		fprintf(stderr, "Valid range is between %d and %d.\n", MIN_PORT, MAX_PORT);
		exit(1);
	}


	/* create a socket for sending to the multicast address */
	if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
	{
		perror("socket() failed");
		exit(1);
	}
	  

	/* set the TTL (time to live/hop count) for the send */
	if ( (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &mc_ttl, sizeof(mc_ttl))) < 0) 
	{
		perror("setsockopt() failed");
		exit(1);
	} 
  

	/* construct a multicast address structure */
	memset(&mc_addr, 0, sizeof(mc_addr));
	mc_addr.sin_family      = AF_INET;
	mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
	mc_addr.sin_port        = htons(mc_port);


	system("top -d 1 -b -n 3 | grep 'Cpu(s):' | tail -n 1 > cpu.txt");
	system("top -d 1 -b -n 1 | grep 'Mem:' > mem.txt");
	FILE* cpu_fp = fopen("cpu.txt", "r");
    FILE* mem_fp = fopen("mem.txt", "r");

	char read_cpu[MAX_LEN],read_mem[MAX_LEN];

	while( fgets(read_cpu, MAX_LEN, cpu_fp) && fgets(read_mem, MAX_LEN, mem_fp) ) 
	{
		char send_str[MAX_LEN];     /* string to send */
		unsigned int send_len;      /* length of string to send */

		float cpu_idle;
		int cpu_load, mem_free, mem_used;
		char *p;
		char *q;

		/* clear send buffer */
		memset(send_str, 0, sizeof(send_str));

		q = strstr (read_cpu, "ni,");
		q += 3;
		sscanf ( q, "%f", &cpu_idle);
		cpu_load = cpu_idle * 10;

		p = strstr (read_mem, ","); 
		sscanf ( ++p, "%d", &mem_used);
		p = strstr (p, ","); 
		sscanf ( ++p, "%d", &mem_free);

		
		/* packet format : 
			 ----------------------------------------------------------------------------------------------
			| node_type |  cpu idle (in range 0-1000) | memory used (in KB) | memory free (in KB)| newline |
			 ----------------------------------------------------------------------------------------------
		*/
		sprintf (send_str, "%d,%d,%d,%d\n", node_type, cpu_load, mem_used, mem_free);
		send_len = strlen(send_str);
		//printf("%s\n", send_str);


		if ((sendto(sock, send_str, send_len, 0, (struct sockaddr *) &mc_addr, sizeof(mc_addr))) != send_len) 
		{
			perror("sendto() sent incorrect number of bytes");
			exit(1);
		}
		
		fclose (cpu_fp);
		fclose (mem_fp);		
		sleep ( MULTICAST_INTERVAL );	


		system("top -d 1 -b -n 3 | grep 'Cpu(s):' | tail -n 1 > cpu.txt");
		system("top -d 1 -b -n 1 | grep 'Mem:' > mem.txt");
		cpu_fp = fopen("cpu.txt", "r");
		mem_fp = fopen("mem.txt", "r");
	}

	close(sock);  
	exit(0);
}


